package com.ruoyi.chatgpt.service.impl;

import cn.hutool.core.util.RandomUtil;
import com.ruoyi.chatgpt.domain.GptDiscount;
import com.ruoyi.chatgpt.domain.GptOrder;
import com.ruoyi.chatgpt.domain.GptTariffPackage;
import com.ruoyi.chatgpt.mapper.GptOrderMapper;
import com.ruoyi.chatgpt.request.AliConfigParam;
import com.ruoyi.chatgpt.request.AlipayBean;
import com.ruoyi.chatgpt.response.PaymentResponseDTO;
import com.ruoyi.chatgpt.service.IGptDiscountService;
import com.ruoyi.chatgpt.service.IGptOrderService;
import com.ruoyi.chatgpt.service.IGptTariffPackageService;
import com.ruoyi.chatgpt.service.PaymentService;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.redis.RedisLock;
import com.ruoyi.common.enums.DiscountTypeEnum;
import com.ruoyi.common.enums.OrderStatusEnum;
import com.ruoyi.common.enums.PayTypeEnum;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.system.service.ISysUserService;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RLock;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;

import static org.slf4j.LoggerFactory.getLogger;

/**
 * 订单Service业务层处理
 * 
 * @author ruoyi
 * @date 2023-06-29
 */
@Service
public class GptOrderServiceImpl implements IGptOrderService 
{
    private static final Logger logger = getLogger(GptOrderServiceImpl.class);
    @Autowired
    private GptOrderMapper gptOrderMapper;

    @Autowired
    private IGptTariffPackageService gptTariffPackageService;

    @Autowired
    private IGptDiscountService gptDiscountService;

    @Autowired
    private RedisLock redisLock;

    @Autowired
    private PaymentService paymentService;

    @Autowired
    private ISysUserService iSysUserService;

    /**
     * 查询订单
     * 
     * @param id 订单主键
     * @return 订单
     */
    @Override
    public GptOrder selectGptOrderById(Long id)
    {
        return gptOrderMapper.selectGptOrderById(id);
    }

    /**
     * 查询订单列表
     * 
     * @param gptOrder 订单
     * @return 订单
     */
    @Override
    public List<GptOrder> selectGptOrderList(GptOrder gptOrder)
    {
        return gptOrderMapper.selectGptOrderList(gptOrder);
    }

    /**
     * 新增订单
     * 
     * @param gptOrder 订单
     * @return 结果
     */
    @Override
    public int insertGptOrder(GptOrder gptOrder)
    {
        gptOrder.setCreateTime(DateUtils.getNowDate());
        return gptOrderMapper.insertGptOrder(gptOrder);
    }

    /**
     * 修改订单
     * 
     * @param gptOrder 订单
     * @return 结果
     */
    @Override
    public int updateGptOrder(GptOrder gptOrder)
    {
        gptOrder.setUpdateTime(DateUtils.getNowDate());
        return gptOrderMapper.updateGptOrder(gptOrder);
    }

    /**
     * 批量删除订单
     * 
     * @param ids 需要删除的订单主键
     * @return 结果
     */
    @Override
    public int deleteGptOrderByIds(Long[] ids)
    {
        return gptOrderMapper.deleteGptOrderByIds(ids);
    }

    /**
     * 删除订单信息
     * 
     * @param id 订单主键
     * @return 结果
     */
    @Override
    public int deleteGptOrderById(Long id)
    {
        return gptOrderMapper.deleteGptOrderById(id);
    }

    @Override
    public Map<String, Object> doConfirm(Long tariffPackageId, String discountCode) {
        //
        Map<String, Object> result = new HashMap<>();
        GptTariffPackage gptTariffPackage = gptTariffPackageService.selectGptTariffPackageById(tariffPackageId);
        if (null == gptTariffPackage) {
            throw new RuntimeException("资费套餐包不存在");
        }
        BigDecimal price = gptTariffPackage.getPrice();
        BigDecimal quantity = gptTariffPackage.getQuantity();
        BigDecimal actualAmt = price;
        BigDecimal actualQuantity = quantity;

        BigDecimal discountValue = new BigDecimal(0);
        if (StringUtils.isNotBlank(discountCode)) {
            GptDiscount gptDiscount = gptDiscountService.queryGptDiscountByCode(discountCode);
            if (null == gptDiscount || gptDiscount.getStatus() == 2 || gptDiscount.getStatus() == 3 || DateUtils.compareTime(new Date(), gptDiscount.getInvalidTime()) > 0) {
                throw new RuntimeException("兑换码无效");
            }

            discountValue = gptDiscount.getQuantity();
            // 计算折扣金额
            if (DiscountTypeEnum.DISCOUNT == gptDiscount.getType()) {
                //
                actualAmt = price.multiply(discountValue);
            } else {
                actualQuantity = quantity.add(discountValue);
            }
        }

        result.put("name", gptTariffPackage.getName());
        result.put("originPrice", gptTariffPackage.getOriginalPrice());
        result.put("price", price);
        result.put("quantity", quantity);
        result.put("actualAmt", actualAmt);
        result.put("actualQuantity", actualQuantity);
        result.put("discountCode", discountCode);
        result.put("discountValue",discountValue);

        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> doSubmit(Long tariffPackageId, String discountCode, PayTypeEnum payType) {
        Map<String, Object> result = new HashMap<>();
        Long userId = SecurityUtils.getUserId();
        String lockName = "order_" + userId;
        String orderCode = null;
        PaymentResponseDTO responseDTO;

        try {
            RLock rLock = redisLock.getRLock(lockName);
            boolean locked = rLock.isLocked();
            if (locked){
                throw new RuntimeException("订单操作繁忙");
            }
            //对同一用户访问加锁
            redisLock.lock(lockName);
            GptTariffPackage gptTariffPackage = gptTariffPackageService.selectGptTariffPackageById(tariffPackageId);
            if (null == gptTariffPackage) {
                throw new RuntimeException("资费套餐包不存在");
            }
            BigDecimal price = gptTariffPackage.getPrice();
            BigDecimal quantity = gptTariffPackage.getQuantity();
            BigDecimal actualAmt = price;
            BigDecimal actualQuantity = gptTariffPackage.getQuantity();

            BigDecimal discountValue = new BigDecimal(0);
            GptDiscount gptDiscount = null;
            if (StringUtils.isNotBlank(discountCode)) {
                gptDiscount = gptDiscountService.queryGptDiscountByCode(discountCode);
                if (null == gptDiscount || gptDiscount.getStatus() == 2 || gptDiscount.getStatus() == 3 || DateUtils.compareTime(new Date(), gptDiscount.getInvalidTime()) > 0) {
                    throw new RuntimeException("兑换码无效");
                }
                discountValue = gptDiscount.getQuantity();
                // 计算折扣金额
                if (DiscountTypeEnum.DISCOUNT == gptDiscount.getType()) {
                    //
                    actualAmt = price.multiply(discountValue);
                } else {
                    actualQuantity = quantity.add(discountValue);
                }
            }
            // 创建订单
            orderCode = createOrder(userId, tariffPackageId, discountCode, payType, actualAmt, actualQuantity);

            // 扣除优惠券
            if (gptDiscount != null) {
                gptDiscountService.updateDiscountStatus(discountCode, userId, gptDiscount.getStatus());
            }

            // 支付下单
            AliConfigParam aliConfigParam = new AliConfigParam();
            AlipayBean alipayBean = new AlipayBean();
            alipayBean.setOutTradeNo(orderCode);
            alipayBean.setTotalAmount(actualAmt.toString());
            alipayBean.setSubject("用户权益充值");
            alipayBean.setBody(gptTariffPackage.getName() +"-"+ gptTariffPackage.getDescription());

            responseDTO = paymentService.createPayOrderByAliWAP(aliConfigParam, alipayBean);
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        } finally {
            //解锁
            redisLock.unlock(lockName);
        }

        result.put("orderCode", orderCode);
        result.put("paymentResponse", responseDTO);
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> queryOrder(String orderCode) {
        Map<String,Object> result = new HashMap<>();
        SysUser sysUser = iSysUserService.selectUserById(SecurityUtils.getUserId());
        GptOrder gptOrder = gptOrderMapper.queryGptOrderByCode(orderCode);
        if (gptOrder == null) {
            throw new RuntimeException("订单号无效");
        }
        OrderStatusEnum orderStatus = OrderStatusEnum.of(gptOrder.getStatus());
        // 支付下单
        AliConfigParam aliConfigParam = new AliConfigParam();
        PaymentResponseDTO responseDTO;
        try {
            responseDTO = paymentService.queryPayOrderByAli(aliConfigParam, orderCode);
            if (Objects.equals(responseDTO.getCode(),"0")) {
                switch (responseDTO.getTradeState()) {
                    case SUCCESS:
                        // 更新订单状态
                        orderStatus = OrderStatusEnum.PAID;
                        // 更新用户剩余数量
                        iSysUserService.updateUserQuantity(sysUser,gptOrder.getQuantity().add(new BigDecimal(sysUser.getQuantity())));
                        break;
                    case FAILED:
                    case REVOKED:
                        orderStatus = OrderStatusEnum.CANCEL_PAYMENT;

                        // discount
                        if(StringUtils.isNotBlank(gptOrder.getDiscountCode())) {
                            GptDiscount gptDiscount = gptDiscountService.queryGptDiscountByCode(gptOrder.getDiscountCode());
                            gptDiscountService.updateDiscountStatus(gptOrder.getDiscountCode(), null, gptDiscount.getStatus());
                        }
                        break;
                }
                gptOrder.setStatus(orderStatus.getCode());
                gptOrder.setUpdateTime(new Date());
                gptOrderMapper.updateGptOrder(gptOrder);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        result.put("orderCode", orderCode);
        result.put("state", orderStatus);
        return result;
    }

    private String createOrder(Long userId, Long packageId, String discountCode, PayTypeEnum payType, BigDecimal actualAmt, BigDecimal actualQuantity) {
        GptOrder order = new GptOrder();
        String orderCode = null;
        try {
            orderCode = DateUtils.dateTimeNow() + RandomUtil.randomNumbers(6);
        } catch (Exception e) {
            logger.error("code generate error:{}", e);
        }
        order.setCode(orderCode);
        order.setDiscountCode(discountCode);
        order.setUserId(userId);
        order.setPackageId(packageId);
        order.setAmount(actualAmt);
        order.setQuantity(actualQuantity);
        order.setPayType(payType.getCode());
        order.setStatus(OrderStatusEnum.UNPAY.getCode());
        Date now = new Date();
        order.setCreateTime(now);
        order.setUpdateTime(now);

        gptOrderMapper.insertGptOrder(order);
        return orderCode;
    }
}
